<!--
	作者：Sariay
	时间：2018-09-25
	描述：There may be a bug, but don't worry, QiLing(器灵) says that it can work normally!
-->
<!DOCTYPE html>
<html class="html-loading">
		

<head><meta name="generator" content="Hexo 3.8.0">
	<meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
  <title>
    
      python进阶 | SorrisoYi
    
  </title>
  <meta name="author" content="SorrisoYi">
  <meta name="keywords" content>
  <meta name="description" content="blog">
	<!-- favicon -->
  <link rel="shortcut icon" href="https://addyzk.github.io/Random-img/favicon.ico">

  <!-- css -->
  <link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="../../../../css/Annie.css">
  
  <!-- jquery -->
	<script src="../../../../js/jquery.min.js"></script>

  <!-- leancloud -->
  <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.4.js"></script>
<script src="../../../../js/leancloud.js"></script>
</head>
	<body>
		<!-- Preloader -->

	<div id="preloader">
		<div class="pre-container">
			
				<div class="spinner">
					<div class="double-bounce1"></div>
					<div class="double-bounce2"></div>
				</div>
						
		</div>
	</div>


<!-- header -->
<header class="fixbackground" data-img-mode data-normal-src="../../../../index.html" data-random-max data-random-src="../../../../index.html">
	<div class="mask">
		<!-- Logo and navigation -->
		<div class="h-header">
			<div id="logo">
				<a href="/">
						
						<img src="https://addyzk.github.io/Random-img/logo.png" alt="Logo">
					
				</a>
			</div>
			
			<div id="navigation-show">
				<ul>
	
		<li class="menu-home">
			<a href="../../../../index.html" class="menu-item-home">主页</a>
		</li>
	
		<li class="menu-archive">
			<a href="../../../.././archives" class="menu-item-archive">归档</a>
		</li>
	
		<li class="menu-categories">
			<a href="../../../.././categories" class="menu-item-categories">分类</a>
		</li>
	
		<li class="menu-tags">
			<a href="../../../.././tags" class="menu-item-tags">标签</a>
		</li>
	
		<li class="menu-about">
			<a href="../../../.././about" class="menu-item-about">关于</a>
		</li>
	
		<li class="menu-gallery">
			<a href="../../../.././gallery" class="menu-item-gallery">相册</a>
		</li>
	

	
		<li class="menu-search">
			<a href="javascript:;" class="popup-trigger">搜索</a>
		</li>
	
</ul>
			</div>				
		</div>

		<!-- motto -->
		<div class="h-body">	
			
				<p class="motto"></p>
			
		</div>
		
		<!-- others: such as time... -->			
		<div class="h-footer">
			<a href="javascript:;" id="read-more"><i class="fa fa-angle-double-down" aria-hidden="true"></i>
			</a>

			
				<!-- 
	This is only a demo, please go to "https://time.is" to set your city time! 
-->
<style type="text/css">
	.header-date {
		font-size: 1.6rem;
		color: #fff;
		position: absolute;
		bottom: 5px;
		right: 1rem;
		writing-mode: tb-rl;
	}	
	
	.header-date a {
		border-bottom: none;
	}

	@media only screen and (max-width: 768 ) {
		.header-date {
			font-size: 1rem;
		}			
	}
</style>
<div class="header-date">
	<a href="https://time.is/Beijing" id="time_is_link" rel="nofollow"></a>
	<span id="Beijing_z43d"></span>
</div>
<script src="//widget.time.is/zh.js"></script>
<script>
	time_is_widget.init({
		Beijing_z43d:{
			template:"DATE", 
			date_format:"year年 monthname dnum日"
		}
	});
</script>
			
		</div>
	</div>
</header>

<div id="navigation-hide">
	<!-- Progress bar -->
	<div id="progress-bar"></div>

	<!-- Progress percent -->
	<div id="progress-percentage"><h1>0.0%</h1></div>

	<div class="toc-switch"><span class="switch-button">目录</span></div>

	<!-- Page title -->
	<p>
		
			当前文章&nbsp;:&nbsp;《python进阶》
		
	</p>

	<!-- Nav trigger for navigation-H-->
	<a class="nav-trigger"><span></span></a>
</div>

<!-- Navigation in div(id="navigation-H") -->
<nav class="nav-container" id="cd-nav">
	<div class="nav-header">
		<h3>Navigation</h3>
		<a href="javascript:;" class="nav-close"></a>
	</div>
	<div class="nav-body">
		<ul>
	
		<li class="menu-home">
			<a href="../../../../index.html" class="menu-item-home">主页</a>
		</li>
	
		<li class="menu-archive">
			<a href="../../../.././archives" class="menu-item-archive">归档</a>
		</li>
	
		<li class="menu-categories">
			<a href="../../../.././categories" class="menu-item-categories">分类</a>
		</li>
	
		<li class="menu-tags">
			<a href="../../../.././tags" class="menu-item-tags">标签</a>
		</li>
	
		<li class="menu-about">
			<a href="../../../.././about" class="menu-item-about">关于</a>
		</li>
	
		<li class="menu-gallery">
			<a href="../../../.././gallery" class="menu-item-gallery">相册</a>
		</li>
	

	
		<li class="menu-search">
			<a href="javascript:;" class="popup-trigger">搜索</a>
		</li>
	
</ul>
	</div>
	<div class="nav-footer">
		<ul>
	
		<li>
			<a href="http://github.com/addyzk" target="_blank">
				<i class="fa fa-github"></i>
			</a>
		</li>
	
		<li>
			<a href="https://weibo.com/u/2943549915" target="_blank">
				<i class="fa fa-weibo"></i>
			</a>
		</li>
	
		<li>
			<a href="http://github.com/" target="_blank">
				<i class="fa fa-pinterest"></i>
			</a>
		</li>
	
		<li>
			<a href="http://github.com/" target="_blank">
				<i class="fa fa-instagram"></i>
			</a>
		</li>
	
		<li>
			<a href="http://github.com/" target="_blank">
				<i class="fa fa-twitter"></i>
			</a>
		</li>
	
		<li>
			<a href="../../../../atom.xml" target="_blank">
				<i class="fa fa-rss"></i>
			</a>
		</li>
			
</ul>

	</div>
</nav>
			
		<!--main-->
		<main>
			<!--
	时间：2018-11-17
	描述：
		插件名称：katelog.min.js
		插件作者：KELEN
		插件来源: https://github.com/KELEN/katelog
-->

	
		<div class="layout-toc">
			<div id="layout-toc">
				<div class="k-catelog-list" id="catelog-list" data-title="文章目录"></div>
			</div>
		</div>

		
		<script src="../../../../plugin/toc/katelog.min.js"></script>

		
	 

<div class="layout-post">
	<div id="layout-post">
	<div class="article-title">
		<i class="fa fa-paper-plane-o" aria-hidden="true"></i>
		
	<a href itemprop="url">
		python进阶
	</a>

	</div>

	<div class="article-meta">
		<span>
			<i class="fa fa-calendar"></i>
			


	发布于

	<a href itemprop="url">
		<time datetime="2019-04-18T09:01:34.000Z" itemprop="datePublished">
	  		2019-04-18
	  </time>
	</a>
	&nbsp;





			




	更新于

	<a href itemprop="url">
		<time datetime="2019-04-18T09:01:34.000Z" itemprop="dateUpdated">
	  		2019-05-18
	  </time>
	</a> 



		</span>
		<span>
			<i class="fa fa-tags"></i>
			
	
		<a href="../../../../tags/python/" class=" ">
			python
		</a>
	
		
		</span>
		
		

	
    <span class="leancloud_visitors" id="_visitors" data-url data-title="python进阶">
       	<i class="fa fa-eye"></i>
       	热度
        <i class="leancloud_visitors_count" id="leancloud_visitors_count">0</i>
    </span>
    



	
    <span class="leancloud_likes" id="_likes" data-url data-title="python进阶" rel="unlike">
        <i class="fa fa-heart"></i>
        喜欢
        <i class="leancloud_likes_count" id="leancloud_likes_count">0</i>
    </span>

	</div>

	<div class="article-content" id="article-content">
		<h1 id="Python-进阶"><a href="#Python-进阶" class="headerlink" title="Python 进阶"></a>Python 进阶</h1><h4 id="1-PEP8-编码规范-及开发中的一些惯例和建议"><a href="#1-PEP8-编码规范-及开发中的一些惯例和建议" class="headerlink" title="1. PEP8 编码规范, 及开发中的一些惯例和建议"></a>1. PEP8 编码规范, 及开发中的一些惯例和建议</h4><p>练习: 规范化这段代码</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> django.conf <span class="keyword">import</span> settings</span><br><span class="line"><span class="keyword">from</span> user.models <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> sys, os</span><br><span class="line">mod=<span class="number">0xffffffff</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span>  <span class="params">( a , b = <span class="number">123</span> )</span>:</span></span><br><span class="line">    c=&#123; <span class="string">'x'</span> : <span class="number">111</span> , <span class="string">'y'</span> : <span class="number">222</span> &#125;<span class="comment">#定义一个字典</span></span><br><span class="line">    d=[ <span class="number">1</span> , <span class="number">3</span>,<span class="number">5</span> ]</span><br><span class="line">    <span class="keyword">return</span> a,b , c</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">bar</span><span class="params">(x)</span>:</span></span><br><span class="line">    <span class="keyword">if</span> x%<span class="number">2</span>==<span class="number">0</span> : <span class="keyword">return</span> <span class="literal">True</span></span><br></pre></td></tr></table></figure>
<p>为什么要有编码规范</p>
<p>编码是给人看的还是给机器看的？</p>
<p>美观是重点吗？</p>
<ol>
<li>美观</li>
<li>可读性</li>
<li>可维护性</li>
<li>健壮性</li>
</ol>
<p>团队内最好的代码状态: 所有人写出的代码像一个人写出来的</p>
<p>代码编排:</p>
<ul>
<li>缩进 4 个空格, 禁止空格与 Tab 混用</li>
<li>行长 80 字符: 防止单行逻辑过于复杂</li>
</ul>
<p><code>import</code></p>
<ul>
<li>不要使用 <code>from xxx import *</code></li>
<li>顺序<ol>
<li>标准库</li>
<li>第三方库</li>
<li>自定义库</li>
</ol>
</li>
<li>单行不要 import 多个库</li>
<li>模块内用不到的不要去 import</li>
</ul>
<p>空格</p>
<ul>
<li><code>: ,</code> 后面跟一个空格, 前面无空格 (行尾分号后无空格)</li>
<li>二元操作符前后各一个空格, 包括以下几类:<ol>
<li>数学运算符: <code>+ - * / // = &amp; |</code></li>
<li>比较运算符: <code>== != &gt; &lt;  &gt;= &lt;= is not in</code></li>
<li>逻辑运算符: <code>and or not</code></li>
<li>位运算符: <code>&amp; | ^ &lt;&lt; &gt;&gt;</code></li>
<li>当 <code>=</code> 用于指示关键字参数或默认参数值时, 不要在其两侧使用空格</li>
</ol>
</li>
</ul>
<p>适当添加空行</p>
<ul>
<li>函数间: 顶级函数间空 2 行, 类的方法之间空 1 行</li>
<li>函数内: 同一函数内的逻辑块之间, 空 1 行</li>
<li>文件结尾: 留一个空行 (Unix 中 \n 是文件的结束符)</li>
</ul>
<p>注释</p>
<ul>
<li><strong>忌</strong>: 逐行添加注释, 没有一个注释</li>
<li>行尾注释: 单行逻辑过于复杂时添加</li>
<li>块注释: 一段逻辑开始时添加</li>
<li>引入外来算法或者配置时须在注释中添加源连接, 标明出处</li>
<li>函数、类、模块尽可能添加 <code>docstring</code>      “””   string  “””</li>
</ul>
<p>命名</p>
<ul>
<li>好的变量名要能做到“词能达意”  见名知意</li>
<li>除非在 lambda 函数中, 否则不要用 <strong>单字母</strong> 的变量名 (即使是 lambda 函数中的变量名也应该尽可能的有意义)</li>
<li>包名、模块名、函数名、方法、普通变量名全部使用小写, 单词间用下划线连接 </li>
<li>类名、异常名使用 CapWords (首字母大写) 的方式, 异常名结尾加 <code>Error</code> 或 <code>Wraning</code> 后缀</li>
<li>全局变量尽量使用大写, 一组同类型的全局变量要加上统一前缀, 单词用下划线连接</li>
<li>函数名必须有动词, 最好是 do_something 的句式, 或者 somebody_do_something 句式</li>
</ul>
<p>语意明确、直白</p>
<ul>
<li><code>not xx in yy</code> <em>VS</em> <code>xx not in yy</code></li>
<li><code>not a is b</code> <em>VS</em> <code>a is not b</code></li>
</ul>
<p>程序的构建</p>
<ul>
<li>函数是模块化思想的体现</li>
<li>独立的逻辑应该抽离成独立函数，让代码结构更清晰，可复用度更高</li>
<li><strong>一个函数只做一件事情, 并把这件事做好</strong></li>
<li><strong>大的功能用小函数之间灵活组合来完成</strong></li>
<li>避免编写庞大的程序, <strong>“大” 意味着体积庞大, 逻辑复杂甚至混乱</strong></li>
</ul>
<p>自定义的变量名、函数名不要与标准库中的名字冲突 </p>
<p><code>pip install pycodestyle pylint flake8 autopep8</code></p>
<h4 id="2-和-的用法"><a href="#2-和-的用法" class="headerlink" title="2. * 和 ** 的用法"></a>2. * 和 ** 的用法</h4><p>函数定义时接收不定长参数</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(*args, **kwargs)</span>:</span></span><br><span class="line">    <span class="keyword">pass</span></span><br></pre></td></tr></table></figure>
<p>参数传递</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(x, y,*,z, a, b)</span>:</span>      <span class="comment"># 此处的*  表示后面的参数必须都是关键字参数</span></span><br><span class="line">    print(x) </span><br><span class="line">    print(y)</span><br><span class="line">    print(z)</span><br><span class="line">    print(a)</span><br><span class="line">    print(b)</span><br><span class="line">lst = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line">dic = &#123;<span class="string">'a'</span>: <span class="number">22</span>, <span class="string">'b'</span>: <span class="number">77</span>&#125;</span><br><span class="line">foo(*lst, **dic)       <span class="comment"># *列表  **字典   解包</span></span><br></pre></td></tr></table></figure>
<p>import * 语法</p>
<p>文件 xyz.py</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">__all__ = (<span class="string">'a'</span>, <span class="string">'e'</span>, <span class="string">'_d'</span>)     <span class="comment"># 指明导包的时候只能倒入  a,e,_d</span></span><br><span class="line"></span><br><span class="line">a = <span class="number">123</span></span><br><span class="line">_b = <span class="number">456</span>                      <span class="comment"># 加了下划线不会被导入</span></span><br><span class="line">c = <span class="string">'asdfghjkl'</span></span><br><span class="line">_d = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>]</span><br><span class="line">e = (<span class="number">9</span>,<span class="number">8</span>,<span class="number">7</span>,<span class="number">6</span>,<span class="number">5</span>,<span class="number">4</span>)</span><br></pre></td></tr></table></figure>
<p>文件abc.py</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> xyz <span class="keyword">import</span> *      <span class="comment"># 只导入了 a,e,_d</span></span><br><span class="line">print(a)</span><br><span class="line">print(_b)</span><br><span class="line">print(c)</span><br><span class="line">print(_d)</span><br><span class="line">print(e)</span><br></pre></td></tr></table></figure>
<h4 id="3-Python-的赋值和引用"><a href="#3-Python-的赋值和引用" class="headerlink" title="3. Python 的赋值和引用"></a>3. Python 的赋值和引用</h4><p><code>==, is</code>: <code>==</code> 判断的是值, <code>is</code> 判断的是内存地址 (即对象的id)</p>
<p>小整数对象: [-5, 256]            # 性能优化   小整数对象内存地址都是一样的，is返回True，大整数  is  返回 false</p>
<p><code>copy, deepcopy</code> 的区别</p>
<p><code>copy</code>: 只拷贝表层元素</p>
<p><code>deepcopy</code>: 在内存中重新创建所有子元素</p>
<p><img src="copy.png" alt="copy and deepcopy"></p>
<p>练习1: 说出执行结果</p>
<p><img src="default_list.png" alt="default list"></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">extendList</span><span class="params">(val, lst=[])</span>:</span></span><br><span class="line">    lst.append(val)</span><br><span class="line">    <span class="keyword">return</span> lst</span><br><span class="line"></span><br><span class="line">list1 = extendList(<span class="number">10</span>)      <span class="comment"># [10]</span></span><br><span class="line">list2 = extendList(<span class="number">123</span>, [])     <span class="comment"># [123]      # []  覆盖了</span></span><br><span class="line">list3 = extendList(<span class="string">'a'</span>)         <span class="comment"># [10,'a']</span></span><br></pre></td></tr></table></figure>
<p>练习2: 说出下面执行结果</p>
<p><img src="copy_deepcopy.png" alt="copy deepcopy"></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> copy <span class="keyword">import</span> copy, deepcopy</span><br><span class="line"><span class="keyword">from</span> pickle <span class="keyword">import</span> dumps, loads</span><br><span class="line"></span><br><span class="line">a = [<span class="string">'x'</span>, <span class="string">'y'</span>, <span class="string">'z'</span>]</span><br><span class="line">b = [a] * <span class="number">3</span> <span class="comment"># [['x','y','z'], ['x','y','z'], ['x','y','z']]     # 三个地址都指向a</span></span><br><span class="line">c = copy(b)</span><br><span class="line">d = deepcopy(b)</span><br><span class="line">e = loads(dumps(b, <span class="number">4</span>))</span><br><span class="line"></span><br><span class="line">b[<span class="number">1</span>].append(<span class="number">999</span>)      <span class="comment"># [['x','y','z',999], ['x','y','z',999], ['x','y','z',999]]</span></span><br><span class="line">b.append(<span class="number">777</span>)</span><br><span class="line"></span><br><span class="line">c[<span class="number">1</span>].append(<span class="number">999</span>)</span><br><span class="line">c.append(<span class="number">555</span>)</span><br><span class="line"></span><br><span class="line">d[<span class="number">1</span>].append(<span class="number">999</span>)</span><br><span class="line">d.append(<span class="number">333</span>)</span><br><span class="line"></span><br><span class="line">e[<span class="number">1</span>].append(<span class="number">999</span>)</span><br><span class="line">e.append(<span class="number">111</span>)</span><br></pre></td></tr></table></figure>
<p>自定义 deepcopy: <code>my_deepcopy = lambda item: loads(dumps(item, 4))</code></p>
<p>dumps  对象序列化    loads   加载，  dumps(item, 4)   4表示协议，协议（1，2，3，4）越高，序列化速度越快</p>
<h4 id="4-迭代器-生成器"><a href="#4-迭代器-生成器" class="headerlink" title="4. 迭代器, 生成器"></a>4. 迭代器, 生成器</h4><p>练习: 说出如下代码的打印结果</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">()</span>:</span></span><br><span class="line"><span class="meta">... </span>   print(<span class="number">111</span>)</span><br><span class="line"><span class="meta">... </span>   <span class="keyword">yield</span> <span class="number">222</span></span><br><span class="line"><span class="meta">... </span>   print(<span class="number">333</span>)</span><br><span class="line"><span class="meta">... </span>   <span class="keyword">yield</span> <span class="number">444</span></span><br><span class="line"><span class="meta">... </span>   print(<span class="number">555</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>n = foo()</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>next(n)</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>next(n)</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>next(n)</span><br></pre></td></tr></table></figure>
<p>generator: 生成器是一种特殊的迭代器, 不需要自定义 <code>__iter__</code> 和 <code>__next__</code></p>
<ul>
<li>生成器函数 (yield)</li>
<li>生成器表达式      ((i  for   i  in range(10))      生成器</li>
</ul>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Range</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, start, end=None, step=<span class="number">1</span>)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> end <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">            self.end = start</span><br><span class="line">            self.start = <span class="number">0</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            self.start = start</span><br><span class="line">            self.end = end</span><br><span class="line">        self.step = step</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__iter__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__next__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> self.start &lt; self.end:</span><br><span class="line">            current = self.start</span><br><span class="line">            self.start += self.step</span><br><span class="line">            <span class="keyword">return</span> current</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">raise</span> StopIteration()</span><br></pre></td></tr></table></figure>
<p>iterator: 任何实现了 <code>__iter__</code> 和 <code>__next__</code> 方法的对象都是迭代器.</p>
<p><code>__iter__</code> 得到一个迭代器。迭代器的<code>__iter__()</code>返回自身</p>
<p><code>__next__</code> 返回迭代器下一个值</p>
<p>如果容器中没有更多元素, 则抛出 StopIteration 异常</p>
<p>Python2中没有 <code>__next__()</code>, 而是 <code>next()</code></p>
<p>可迭代对象是指实现了<code>__iter__</code>方法，没有实现<code>__next__</code>方法</p>
<p><code>str / bytes / list / tuple / dict / set</code> 自身不是迭代器，他们自身不具备 <code>__next__()</code>, 但是具有 <code>__iter__()</code>, <code>__iter__()</code> 方法用来把自身转换成一个迭代器</p>
<p>练习1: 定义一个随机数迭代器, 随机范围为 [1, 50], 最大迭代次数 30</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> random</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">RandomIter</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, start, end, times)</span>:</span></span><br><span class="line">        self.start = start</span><br><span class="line">        self.end = end</span><br><span class="line">        self.count = times</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__iter__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__next__</span><span class="params">(self)</span>:</span></span><br><span class="line">        self.count -= <span class="number">1</span></span><br><span class="line">        <span class="keyword">if</span> self.count &gt;= <span class="number">0</span>:</span><br><span class="line">            <span class="keyword">return</span> random.randint(self.start, self.end)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">raise</span> StopIteration()</span><br></pre></td></tr></table></figure>
<p>练习2: 自定义一个迭代器, 实现斐波那契数列</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Fib</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, max_value)</span>:</span></span><br><span class="line">        self.prev = <span class="number">0</span></span><br><span class="line">        self.curr = <span class="number">1</span></span><br><span class="line">        self.max_value = max_value</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__iter__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__next__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> self.curr &lt;= self.max_value:</span><br><span class="line">            res = self.curr</span><br><span class="line">            self.prev, self.curr = self.curr, self.prev + self.curr  <span class="comment"># 为下一次做准备</span></span><br><span class="line">            <span class="keyword">return</span> res</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">raise</span> StopIteration()</span><br></pre></td></tr></table></figure>
<p>练习3: 自定义一个生成器函数, 实现斐波那契数列</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">(max_value)</span>:</span></span><br><span class="line">    prev = <span class="number">0</span></span><br><span class="line">    curr = <span class="number">1</span></span><br><span class="line">    <span class="keyword">while</span> curr &lt; max_value:</span><br><span class="line">        <span class="keyword">yield</span> curr</span><br><span class="line">        prev, curr = curr, curr + prev</span><br></pre></td></tr></table></figure>
<p>迭代器、生成器有什么好处？</p>
<ul>
<li>节省内存</li>
<li>惰性求值 （惰性求值思想来自于 Lisp 语言） </li>
</ul>
<p>各种推导式</p>
<ul>
<li>分三部分：生成值的表达式, 循环主体, 过滤条件表达式</li>
<li>列表: <code>[i * 3 for i in range(5) if i % 2 == 0]</code></li>
<li>字典: <code>{i: i + 3 for i in range(5)}</code></li>
<li>集合: <code>{i for i in range(5)}</code></li>
</ul>
<h4 id="5-装饰器-AOP编程思想，-面向切面编程"><a href="#5-装饰器-AOP编程思想，-面向切面编程" class="headerlink" title="5. 装饰器      AOP编程思想， 面向切面编程"></a>5. 装饰器      AOP编程思想， 面向切面编程</h4><p>最简装饰器</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> functools <span class="keyword">import</span> wraps</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">deco_outter</span><span class="params">(n)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">deco</span><span class="params">(func)</span>:</span></span><br><span class="line"><span class="meta">        @wraps(func)</span></span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">wrap</span><span class="params">(*args, **kwargs)</span>:</span></span><br><span class="line">            <span class="keyword">return</span> func(*args, **kwargs)</span><br><span class="line">        <span class="keyword">return</span> wrap</span><br><span class="line">    <span class="keyword">return</span> deco</span><br><span class="line"></span><br><span class="line"><span class="meta">@deco(10)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(a, b)</span>:</span></span><br><span class="line">    <span class="keyword">return</span> a ** b</span><br></pre></td></tr></table></figure>
<p>原理</p>
<p>对比被装饰前后的 <code>foo.__name__</code> 和 <code>foo.__doc__</code></p>
<p>装饰器改变了原函数的doctoring和name    使用wraps装饰器解决</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> functools <span class="keyword">import</span> wraps</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">deco</span><span class="params">(func)</span>:</span></span><br><span class="line">    <span class="string">'''i am deco'''</span></span><br><span class="line"><span class="meta">    @wraps(func)  # 还原被装饰器修改的原函数属性</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">wrap</span><span class="params">(*args, **kwargs)</span>:</span></span><br><span class="line">        <span class="string">'''i am wrap'''</span></span><br><span class="line">        <span class="keyword">return</span> func(*args, **kwargs)</span><br><span class="line">    <span class="keyword">return</span> wrap</span><br></pre></td></tr></table></figure>
<p>简单过程</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">fn = deco(func)</span><br><span class="line">foo = fn</span><br><span class="line">foo(*args, **kwargs)</span><br></pre></td></tr></table></figure>
<p>多个装饰器叠加调用的过程</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@deco1</span></span><br><span class="line"><span class="meta">@deco2</span></span><br><span class="line"><span class="meta">@deco3</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(x, y)</span>:</span></span><br><span class="line">    <span class="keyword">return</span> x ** y</span><br><span class="line"></span><br><span class="line"><span class="comment"># 过程拆解 1</span></span><br><span class="line">fn3 = deco3(foo)</span><br><span class="line">fn2 = deco2(fn3)</span><br><span class="line">fn1 = deco1(fn2)</span><br><span class="line">foo = fn1</span><br><span class="line">foo(<span class="number">3</span>, <span class="number">4</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 过程拆解 2</span></span><br><span class="line"><span class="comment"># 单行: deco1( deco2( deco3(foo) ) )(3, 2)</span></span><br><span class="line">deco1(</span><br><span class="line">    deco2(</span><br><span class="line">        deco3(foo)</span><br><span class="line">    )</span><br><span class="line">)(<span class="number">3</span>, <span class="number">4</span>)</span><br></pre></td></tr></table></figure>
<p>带参数的装饰器</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">deco</span><span class="params">(n)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">wrap1</span><span class="params">(func)</span>:</span></span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">wrap2</span><span class="params">(*args, **kwargs)</span>:</span></span><br><span class="line">            <span class="keyword">return</span> func(*args, **kwargs)</span><br><span class="line">        <span class="keyword">return</span> wrap2</span><br><span class="line">    <span class="keyword">return</span> wrap1</span><br><span class="line"></span><br><span class="line"><span class="comment"># 调用过程</span></span><br><span class="line">wrap1 = deco(n)</span><br><span class="line">wrap2 = wrap1(foo)</span><br><span class="line">foo = wrap2</span><br><span class="line">foo()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 单行形式</span></span><br><span class="line">check_result(<span class="number">30</span>)(foo)(<span class="number">4</span>, <span class="number">8</span>)</span><br></pre></td></tr></table></figure>
<p>装饰器类和 <code>__call__</code></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Deco</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, func)</span>:</span></span><br><span class="line">        self.func = func</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__call__</span><span class="params">(self, *args, **kwargs)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self.func(*args, **kwargs)</span><br><span class="line"></span><br><span class="line"><span class="meta">@Deco</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(x, y)</span>:</span></span><br><span class="line">    <span class="keyword">return</span> x ** y</span><br><span class="line"></span><br><span class="line"><span class="comment"># 过程拆解</span></span><br><span class="line">fn = Deco(foo)</span><br><span class="line">foo = fn</span><br><span class="line">foo(<span class="number">12</span>, <span class="number">34</span>)</span><br></pre></td></tr></table></figure>
<p>使用场景</p>
<ul>
<li>参数、结果检查</li>
<li>缓存、计数</li>
<li>日志、统计</li>
<li>权限管理</li>
<li>重试</li>
<li>其他</li>
</ul>
<p>练习1: 写一个 timer 装饰器, 计算出被装饰函数调用一次花多长时间, 并把时间打印出来</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">from</span> functools <span class="keyword">import</span> wraps</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">timer</span><span class="params">(func)</span>:</span></span><br><span class="line"><span class="meta">    @wraps(func)  # 修正 docstring</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">wrap</span><span class="params">(*args, **kwargs)</span>:</span></span><br><span class="line">        time0 = time.time()</span><br><span class="line">        result = func(*args, **kwargs)</span><br><span class="line">        time1 = time.time()</span><br><span class="line">        print(time1 - time0)</span><br><span class="line">        <span class="keyword">return</span> result</span><br><span class="line">    <span class="keyword">return</span> wrap</span><br></pre></td></tr></table></figure>
<p>练习2: 写一个 Retry 装饰器</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">retry</span><span class="params">(object)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, max_retries=<span class="number">3</span>, wait=<span class="number">0</span>, exceptions=<span class="params">(Exception,)</span>)</span>:</span></span><br><span class="line">        self.max_retries = max_retries</span><br><span class="line">        self.exceptions = exceptions</span><br><span class="line">        self.wait = wait</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__call__</span><span class="params">(self, func)</span>:</span></span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">wrapper</span><span class="params">(*args, **kwargs)</span>:</span></span><br><span class="line">            <span class="keyword">for</span> i <span class="keyword">in</span> range(self.max_retries + <span class="number">1</span>):</span><br><span class="line">                <span class="keyword">try</span>:</span><br><span class="line">                    result = func(*args, **kwargs)</span><br><span class="line">                <span class="keyword">except</span> self.exceptions:</span><br><span class="line">                    time.sleep(self.wait)</span><br><span class="line">                    <span class="keyword">continue</span></span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="keyword">return</span> result</span><br><span class="line">        <span class="keyword">return</span> wrapper</span><br></pre></td></tr></table></figure>
<h4 id="6-函数闭包"><a href="#6-函数闭包" class="headerlink" title="6. 函数闭包"></a>6. 函数闭包</h4><p>Function Closure: 引用了自由变量的函数即是一个闭包. 这个被引用的自由变量和这个函数一同存在, 即使已经离开了创造它的环境也不例外.</p>
<p>说出下面函数返回值</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">()</span>:</span></span><br><span class="line">    l = []</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">bar</span><span class="params">(i)</span>:</span></span><br><span class="line">        l.append(i)</span><br><span class="line">        <span class="keyword">return</span> l</span><br><span class="line">    <span class="keyword">return</span> bar</span><br><span class="line"></span><br><span class="line">f1 = foo()</span><br><span class="line">f2 = foo()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 说出下列语句执行结果</span></span><br><span class="line">f1(<span class="number">1</span>)        <span class="comment"># l = [1]</span></span><br><span class="line">f1(<span class="number">2</span>)        <span class="comment"># l = [1,2]</span></span><br><span class="line">f2(<span class="number">3</span>)        <span class="comment"># l = [3]</span></span><br></pre></td></tr></table></figure>
<p>深入一点: <code>object.__closure__</code>   （对象，）    <code>list_cell, = object.__closure__</code> 解包 </p>
<p><code>object.cell_contents</code> 返回闭包中自由变量的值</p>
<p>作用域</p>
<figure class="highlight mel"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">┌───────────────────────────┐</span><br><span class="line">│ built-<span class="keyword">in</span> <span class="keyword">namespace</span>        │</span><br><span class="line">├───────────────────────────┤  ↑</span><br><span class="line">│ <span class="keyword">global</span> <span class="keyword">namespace</span>          │</span><br><span class="line">│   ┌───────────────────────┤</span><br><span class="line">│   │ local <span class="keyword">namespace</span>       │  n = <span class="number">123</span></span><br><span class="line">│   │   ┌───────────────────┤</span><br><span class="line">│   │   │ local <span class="keyword">namespace</span>   │  ↑</span><br><span class="line">│   │   │   ┌───────────────┤</span><br><span class="line">│   │   │   │ ...           │  <span class="keyword">print</span>(n)</span><br><span class="line">└───┴───┴───┴───────────────┘</span><br></pre></td></tr></table></figure>
<p>声明全局变量: <code>global</code></p>
<p>声明非本层的 <strong>局部变量</strong> : <code>nonlocal</code></p>
<p>查看全局变量: <code>globals()</code></p>
<ul>
<li>查看局部变量: <code>locals()</code><ul>
<li>查看变量: <code>vars([object])  # 不传参数相当于 locals(), 传入对象后, 会得到 object.__dict__</code></li>
</ul>
</li>
</ul>
<h4 id="7-类方法和静态方法"><a href="#7-类方法和静态方法" class="headerlink" title="7. 类方法和静态方法"></a>7. 类方法和静态方法</h4><p><code>method</code> 普通方法</p>
<ul>
<li>通过实例调用</li>
<li>可以引用类内部的<strong>任何属性和方法</strong></li>
<li>第一个参数是self，代表实例对象本身</li>
</ul>
<p><code>classmethod</code></p>
<ul>
<li>无需实例化，实例对象和类名都可以调用</li>
<li>可以调用类属性和类方法</li>
<li>无法取到普通的成员属性和方法</li>
<li>第一个参数是cls,表示类本身</li>
</ul>
<p><code>staticmethod</code></p>
<ul>
<li>无需实例化</li>
<li><strong>无法</strong>取到类内部的任何属性和方法, 完全独立的一个方法</li>
<li>无需传任何参数</li>
</ul>
<p>练习: 说出下面代码的运行结果</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span><span class="params">(object)</span>:</span></span><br><span class="line">    x = <span class="number">123</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">        self.y = <span class="number">456</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">bar1</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'i am a method'</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">    @classmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">bar2</span><span class="params">(cls)</span>:</span></span><br><span class="line">        print(<span class="string">'i am a classmethod'</span>)</span><br><span class="line"></span><br><span class="line"><span class="meta">    @staticmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">bar3</span><span class="params">()</span>:</span></span><br><span class="line">        print(<span class="string">'i am a staticmethod'</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">foo1</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(self.x)</span><br><span class="line">        print(self.y)</span><br><span class="line">        self.bar1()       <span class="comment"># 可以</span></span><br><span class="line">        self.bar2()       <span class="comment"># 可以</span></span><br><span class="line">        self.bar3()       <span class="comment"># 可以</span></span><br><span class="line"></span><br><span class="line"><span class="meta">    @classmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">foo2</span><span class="params">(cls)</span>:</span></span><br><span class="line">        print(cls.x)</span><br><span class="line">        print(cls.y) <span class="comment"># 会报错  y是实例属性，不能被类方法调用</span></span><br><span class="line">        cls.bar1() <span class="comment"># 会报错,因为bar1是实例方法. 得通过self.bar1</span></span><br><span class="line">        cls.bar2()       <span class="comment"># 可以</span></span><br><span class="line">        cls.bar3()       <span class="comment"># 可以</span></span><br><span class="line"></span><br><span class="line"><span class="meta">    @staticmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">foo3</span><span class="params">(obj)</span>:</span></span><br><span class="line">        print(obj.x)</span><br><span class="line">        print(obj.y)</span><br><span class="line">        obj.bar1()</span><br><span class="line">        obj.bar2()</span><br><span class="line">        obj.bar3()</span><br><span class="line"></span><br><span class="line">t = Test()</span><br><span class="line">t.foo1()</span><br><span class="line">t.foo2()</span><br><span class="line">t.foo3()                <span class="comment"># 传t进去就可以</span></span><br></pre></td></tr></table></figure>
<h4 id="8-继承相关问题"><a href="#8-继承相关问题" class="headerlink" title="8. 继承相关问题"></a>8. 继承相关问题</h4><p>什么是多态</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'animal running'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Lion</span><span class="params">(Animal)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'lion running'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Tiger</span><span class="params">(Animal)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'tiger running'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LionTiger</span><span class="params">(Lion, Tiger)</span>:</span></span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">cub = LionTiger()</span><br><span class="line">cub.run()           <span class="comment"># lion running</span></span><br><span class="line">isinstance(cub, Lion)      <span class="comment"># true</span></span><br><span class="line">isinstance(cub, Tiger)     <span class="comment"># true    一个对象可以是多个类，就是多态</span></span><br></pre></td></tr></table></figure>
<p>多继承</p>
<p>方法和属性的继承顺序: <code>Cls.mro()</code>  继承链</p>
<p>菱形继承问题</p>
<figure class="highlight gcode"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">继承关系示意</span><br><span class="line">菱形继承</span><br><span class="line">     A.foo<span class="comment">()</span></span><br><span class="line">   /   \</span><br><span class="line">  B     C.foo<span class="comment">()</span></span><br><span class="line">   \   /</span><br><span class="line">     D.mro<span class="comment">()</span>  <span class="attr"># 方法的继承顺序，由 C3</span> 算法得到</span><br></pre></td></tr></table></figure>
<p>Mixin: 通过单纯的 mixin 类完成功能组合</p>
<p>super 会根据执行链去调用</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'enter A'</span>)</span><br><span class="line">        self.x = <span class="number">111</span></span><br><span class="line">        print(<span class="string">'exit A'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span><span class="params">(A)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'enter B'</span>)</span><br><span class="line">        self.y = <span class="number">222</span></span><br><span class="line">        A.__init__(self)      <span class="comment"># 执行父类方法不推荐使用。推荐使用super()</span></span><br><span class="line">        <span class="comment"># super().__init__()</span></span><br><span class="line">        print(<span class="string">'exit B'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span><span class="params">(A)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'enter C'</span>)</span><br><span class="line">        self.z = <span class="number">333</span></span><br><span class="line">        A.__init__(self)</span><br><span class="line">        <span class="comment"># super().__init__()</span></span><br><span class="line">        print(<span class="string">'exit C'</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">D</span><span class="params">(B, C)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">        print(<span class="string">'enter D'</span>)</span><br><span class="line">        B.__init__(self)</span><br><span class="line">        C.__init__(self)</span><br><span class="line">        <span class="comment"># super().__init__()         # super只执行一次A方法</span></span><br><span class="line">        print(<span class="string">'exit D'</span>)</span><br><span class="line"></span><br><span class="line">d = D()</span><br></pre></td></tr></table></figure>
<h4 id="9-垃圾收集-GC-引用计数，标记清除，分代收集"><a href="#9-垃圾收集-GC-引用计数，标记清除，分代收集" class="headerlink" title="9. 垃圾收集 (GC)            引用计数，标记清除，分代收集"></a>9. 垃圾收集 (GC)            引用计数，标记清除，分代收集</h4><p>Garbage Collection (GC)</p>
<p>引用计数</p>
<p>优点: 简单、实时性高</p>
<p><img src="gc1.png" alt="GC">  ==&gt;  <img src="gc2.png" alt="GC"></p>
<p>缺点: 消耗资源、循环引用</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">lst1 = [<span class="number">3</span>, <span class="number">4</span>]           <span class="comment"># lst1-&gt;ref_count 1</span></span><br><span class="line">lst2 = [<span class="number">8</span>, <span class="number">9</span>]           <span class="comment"># lst2-&gt;ref_count 1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># lst1 -&gt; [3, 4, lst2]</span></span><br><span class="line">lst1.append(lst2)       <span class="comment"># lst2-&gt;ref_count 2</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># lst2 -&gt; [8, 9, lst1]</span></span><br><span class="line">lst2.append(lst1)       <span class="comment"># lst1-&gt;ref_count 2</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">del</span> lst1                <span class="comment"># lst1-&gt;ref_count 1</span></span><br><span class="line"><span class="keyword">del</span> lst2                <span class="comment"># lst2-&gt;ref_count 1</span></span><br></pre></td></tr></table></figure>
<p><img src="ref_loop.jpg" alt="ref_loop"></p>
<p>标记-清除, 分代收集（老，中，新）        # 循环引用的话引用计数没法清除，使用标记清除（链表）</p>
<p>用来回收引用计数无法清除的内存</p>
<h4 id="10-Python-魔术方法"><a href="#10-Python-魔术方法" class="headerlink" title="10. Python 魔术方法"></a>10. Python 魔术方法</h4><p><code>__str__</code> 格式化输出对象     print 的时候调用</p>
<p><code>__repr__</code>   实现此方法，则可以用<code>__str__</code>方法中的内容代替对象本身</p>
<p><code>__init__</code> 和 <code>__new__</code></p>
<ul>
<li><code>__new__</code> 创建一个实例，并返回类的实例</li>
<li><code>__init__</code> 初始化实例，无返回值</li>
<li><p><code>__new__</code> 是一个特殊的类方法,不需要使用@classmethod来装饰.</p>
<ul>
<li>单例模式          或者  利用python模块的唯一属性，新建一个py文件，实例化一个类，导包就可以  <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span><span class="params">(object)</span>:</span></span><br><span class="line">    <span class="string">'''单例模式'''</span></span><br><span class="line">    obj = <span class="literal">None</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__new__</span><span class="params">(cls, *args, **kwargs)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> cls.obj <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">            cls.obj = object.__new__(cls)</span><br><span class="line">        <span class="keyword">return</span> cls.obj</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
<p>数学运算、比较运算</p>
<ul>
<li><p>运算符重载</p>
<ul>
<li><code>+</code>: <code>__add__(value)</code></li>
<li><code>-</code>: <code>__sub__(value)</code>   substract</li>
<li><code>*</code>: <code>__mul__(value)</code>   mulply</li>
<li><code>/</code>: <code>__truediv__(value)</code> (Python 3.x), <code>__div__(value)</code> (Python 2.x)  divide</li>
<li><code>//</code>: <code>__floordiv__(value)</code></li>
<li><code>%</code>: <code>__mod__(value)</code></li>
<li><code>&amp;</code>: <code>__and__(value)</code></li>
<li><code>|</code>: <code>__or__(value)</code></li>
</ul>
</li>
<li><p>练习: 实现字典的 <code>__add__</code> 方法, 作用相当于 d.update(other)</p>
  <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Dict</span><span class="params">(dict)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__add__</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        <span class="keyword">if</span> isinstance(other, dict):</span><br><span class="line">            new_dict = &#123;&#125;</span><br><span class="line">            new_dict.update(self)</span><br><span class="line">            new_dict.update(other)</span><br><span class="line">            <span class="keyword">return</span> new_dict</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">raise</span> TypeError(<span class="string">'not a dict'</span>)</span><br></pre></td></tr></table></figure>
</li>
<li><p>比较运算符的重载</p>
<ul>
<li><code>==</code>: <code>__eq__(value)</code> </li>
<li><code>!=</code>: <code>__ne__(value)</code>  </li>
<li><code>&gt;</code>: <code>__gt__(value)</code></li>
<li><code>&gt;=</code>: <code>__ge__(value)</code></li>
<li><code>&lt;</code>: <code>__lt__(value)</code></li>
<li><code>&lt;=</code>: <code>__le__(value)</code></li>
</ul>
</li>
<li><p>练习: 完成一个类, 实现数学上无穷大的概念      应该写成一个单例，实例化两个对象后会出现矛盾</p>
  <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Inf</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__lt__</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__le__</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__ge__</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__gt__</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__eq__</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">False</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__ne__</span><span class="params">(self, other)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">True</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<ol>
<li><p>容器方法</p>
<p> <code>__len__</code> -&gt; len</p>
<p> <code>__iter__</code> -&gt; for</p>
<p> <code>__contains__</code> -&gt; in</p>
<p> <code>__getitem__</code> 对 <code>string, bytes, list, tuple, dict</code> 有效</p>
<p> <code>__setitem__</code> 对 <code>list, dict</code> 有效</p>
<p> <code>__missing__</code> 对 dict 有效, 字典的预留接口, dict 本身并没有实现 </p>
 <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Dict</span><span class="params">(dict)</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__missing__</span><span class="params">(self, key)</span>:</span></span><br><span class="line">        self[key] = <span class="literal">None</span> <span class="comment"># 当检查到 Key 缺失时, 可以做任何默认行为</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>可执行对象: <code>__call__</code></p>
</li>
<li><p>上下文管理 with:</p>
<p> <code>__enter__</code> 进入 <code>with</code> 代码块前的准备操作</p>
<p> <code>__exit__</code> 退出时的善后操作</p>
<p> 文件对象、线程锁、socket 对象 等 都可以使用 with 操作</p>
<p> 示例</p>
 <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__enter__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__exit__</span><span class="params">(self, Error, error, traceback)</span>:</span></span><br><span class="line">        print(Error, error, traceback)</span><br></pre></td></tr></table></figure>
</li>
<li><p>python的自省<code>__setattr__, __getattribute__, __getattr__, __dict__</code></p>
<p> 内建函数：<code>setattr(), getattr(), hasattr()</code>  python的内省.</p>
<p> 常用来做属性监听</p>
 <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">User</span>:</span></span><br><span class="line">    <span class="string">'''TestClass'''</span></span><br><span class="line">    z = [<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>]</span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">        self.money = <span class="number">10000</span></span><br><span class="line">        self.y = <span class="string">'abc'</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__setattr__</span><span class="params">(self, name, value)</span>:</span>        <span class="comment"># setattr()设置实例属性</span></span><br><span class="line">        <span class="keyword">if</span> name == <span class="string">'money'</span> <span class="keyword">and</span> value &lt; <span class="number">0</span>:</span><br><span class="line">            <span class="keyword">raise</span> ValueError(<span class="string">'money &lt; 0'</span>)</span><br><span class="line">        print(<span class="string">'set %s to %s'</span> % (name, value))</span><br><span class="line">        object.__setattr__(self, name, value)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__getattribute__</span><span class="params">(self, name)</span>:</span>   <span class="comment"># getattr()获取属性 第三个参数返回默认值，不再报错</span></span><br><span class="line">        print(<span class="string">'get %s'</span> % name)</span><br><span class="line">        <span class="keyword">return</span> object.__getattribute__(self, name)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__getattr__</span><span class="params">(self, name)</span>:</span>        <span class="comment"># 当拿不到属性的时候，调用此方法</span></span><br><span class="line">        print(<span class="string">'not has %s'</span> % name)</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>											 <span class="comment"># hasattr()  判断是否有属性,对应__dict__魔术方法</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(self, x, y)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> x ** y</span><br><span class="line"></span><br><span class="line"><span class="comment"># 对比</span></span><br><span class="line">a = User()</span><br><span class="line">print(User.__dict__)</span><br><span class="line">print(a.__dict__)</span><br></pre></td></tr></table></figure>
</li>
<li><p>槽: <code>__slots__</code></p>
<p> 固定类所具有的属性，不能动态添加属性</p>
<p> 实例不会分配 <code>__dict__</code></p>
<p> 实例无法动态添加属性</p>
<p> 优化内存分配, 大概能节约40%的内存.</p>
 <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span>:</span></span><br><span class="line">    __slots__ = (<span class="string">'x'</span>, <span class="string">'y'</span>)</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="11-Python-性能之困"><a href="#11-Python-性能之困" class="headerlink" title="11. Python 性能之困"></a>11. Python 性能之困</h4><p>1、计算密集型</p>
<p>CPU 长时间满负荷运行, 如图像处理、大数据运算、圆周率计算等</p>
<p>计算密集型: 用 C 语言补充或者换编译器，目前是Cpython， 试试Pypi</p>
<p>Profile, timeit     选择进程</p>
<p>2、I/O 密集型  (input/output)</p>
<p>网络 IO, 文件 IO, 设备 IO 等</p>
<p>一切皆文件    选择线程</p>
<p>3、多任务处理</p>
<p>进程、线程、协程调度的过程叫做上下文切换</p>
<p>进程、线程、协程对比</p>
<p>进程是系统资源分配的最小单位。线程是系统调度的最小单位。协程是微线程，是线程的进化</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>资源占用</th>
<th>数据通信</th>
<th>上下文切换 (Context)</th>
</tr>
</thead>
<tbody>
<tr>
<td> 进程</td>
<td>大(M)</td>
<td>不方便 (网络、共享内存、管道等)</td>
<td>操作系统按时间片切换, 不够灵活, 慢</td>
</tr>
<tr>
<td> 线程</td>
<td>小(k)</td>
<td>非常方便</td>
<td>按时间片切换, 不够灵活, 快</td>
</tr>
<tr>
<td> 协程</td>
<td>非常小(bytes)</td>
<td>非常方便</td>
<td>根据I/O事件切换, 更加有效的利用 CPU</td>
</tr>
</tbody>
</table>
<p>1、全局解释器锁 ( GIL )</p>
<p>它确保任何时候一个进程中都只有一个 Python 线程能进入 CPU 执行。</p>
<p>全局解释器锁造成单个进程无法使用多个 CPU 核心</p>
<p>通过多进程来利用多个 CPU 核心，一般进程数与CPU核心数相等，或者CPU核心数两倍<br><img src="GIL.png" alt="GIL" title="GIL"></p>
<p>2、什么是同步、异步、阻塞、非阻塞？</p>
<p>同步, 异步: 客户端调用服务器接口时</p>
<p>阻塞, 非阻塞: 服务端发生等待</p>
<p>阻塞 -&gt; 非阻塞  (阻塞是停下来等待,非阻塞是不会等待, 解决io单个任务问题.)  </p>
<p>同步 -&gt; 异步 (同步 是 任务一个 接一个执行,异步是任务同时执行.解决任务量大的问题)</p>
<p>3、事件驱动 + 多路复用</p>
<p>轮询: select, poll </p>
<p>事件驱动: epoll 基于事件的有效轮询 (e:event )</p>
<p>4、协程：Stackless / greenlets / gevent | tornado / asyncio</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> asyncio      <span class="comment"># 官方协程包</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">(n)</span>:</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">10</span>):</span><br><span class="line">        print(<span class="string">'wait %s s'</span> % n)</span><br><span class="line">        <span class="keyword">await</span> asyncio.sleep(n)     <span class="comment"># 异步io   asyncio</span></span><br><span class="line">    <span class="keyword">return</span> i</span><br><span class="line"></span><br><span class="line">task1 = foo(<span class="number">1</span>)          <span class="comment"># 没有执行</span></span><br><span class="line">task2 = foo(<span class="number">1.5</span>)        <span class="comment"># 此处没有执行</span></span><br><span class="line">tasks = [asyncio.ensure_future(task1),</span><br><span class="line">         asyncio.ensure_future(task2)]</span><br><span class="line"></span><br><span class="line">loop = asyncio.get_event_loop()  <span class="comment"># 事件循环，协程调度器</span></span><br><span class="line">loop.run_until_complete( asyncio.wait(tasks))</span><br></pre></td></tr></table></figure>
<p>5、线程安全, 锁</p>
<ul>
<li>获得锁之后, 一定要释放, 避免死锁 </li>
<li>尽量使用 with 去操作锁</li>
<li>获得锁之后, 执行的语句, 只跟被锁资源有关</li>
<li>线程之间的数据交互尽量使用 queue</li>
</ul>
<h4 id="12-一些技巧和误区"><a href="#12-一些技巧和误区" class="headerlink" title="12. 一些技巧和误区"></a>12. 一些技巧和误区</h4><p>1、格式化打印 json        indent  缩进；sort_keys  字母表排序；ensure_ascii=False 允许显示中文</p>
<ul>
<li>调试时数据格式化：<code>json.dumps(data, indent=4, sort_keys=True, ensure_ascii=False)</code></li>
<li>传输时 json 压缩: <code>json.dumps(data, ensure_ascii=False, separators=[&#39;,&#39;,&#39;:&#39;])</code></li>
</ul>
<p>2、确保能取到有效值</p>
<ul>
<li><code>d.get(k, default)</code>  无值时使用默认值，对原字典无修改</li>
<li><code>d.setdefault</code> 无值时使用默认值，并将默认值写入原字典</li>
<li><code>x = a if foo() else b</code>   三元运算符</li>
<li><code>a or b</code>   python中所有的对象都有真值, or返回真的, and是遇到假的就返回.</li>
</ul>
<p>3、try…except… 的滥用</p>
<ul>
<li>不要把所有东西全都包住, 程序错误需要报出来</li>
<li>使用 <code>try...except</code> 要指明具体错误, <code>try</code> 结构不是用来隐藏错误的, 而是用来有方向的处理错误的</li>
</ul>
<p>4、利用 dict 做模式匹配</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">do1</span><span class="params">()</span>:</span></span><br><span class="line">    print(<span class="string">'i am do1'</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">do2</span><span class="params">()</span>:</span></span><br><span class="line">    print(<span class="string">'i am do2'</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">do3</span><span class="params">()</span>:</span></span><br><span class="line">    print(<span class="string">'i am do3'</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">do4</span><span class="params">()</span>:</span></span><br><span class="line">    print(<span class="string">'i am do4'</span>)</span><br><span class="line"></span><br><span class="line">mapping = &#123;<span class="number">1</span>: do1, <span class="number">2</span>: do2, <span class="number">3</span>: do3, <span class="number">4</span>: do4&#125;</span><br><span class="line">mod = random.randint(<span class="number">1</span>, <span class="number">10</span>)</span><br><span class="line">func = mapping.get(mod, do4)    <span class="comment"># 默认do4</span></span><br><span class="line">func()</span><br></pre></td></tr></table></figure>
<p>1、<code>inf, -inf, nan</code>       inf  无穷大   float(‘inf’)    </p>
<p>2、字符串拼接尽量使用 <code>join</code> 方式: 速度快, 内存消耗小</p>
<p>3、property: 把一个方法属性化</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span><span class="params">(object)</span>:</span></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">x</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""I am the 'x' property."""</span></span><br><span class="line">        <span class="keyword">return</span> self._x</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># c.x = xx  user.password</span></span><br><span class="line"><span class="meta">    @x.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">x</span><span class="params">(self, value)</span>:</span></span><br><span class="line">    	self._x = value</span><br><span class="line">        </span><br><span class="line"><span class="meta">    @x.deleter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">x</span><span class="params">(self)</span>:</span> </span><br><span class="line">    	<span class="keyword">del</span> self._x</span><br></pre></td></tr></table></figure>
<p>4、else 子句: <code>if, for, while, try</code></p>
<p>5、collections 模块     from collections import  defaultdict , OrderedDict, Counter , namedtuple</p>
<ul>
<li><p>defaultdict (可调用对象，字典)</p>
</li>
<li><p>OrderedDict     有序字典</p>
</li>
<li><p>Counter    计数器     可以计数字符串字符出现的次数</p>
<p>c = Counter()</p>
<p>c[n] += 1</p>
</li>
<li><p>namedtuple    命名元组</p>
<p>Dog = namedtuple(‘Dog’, [‘head’, ‘body’, ‘leg’, ‘tail’])</p>
<p>dog = Dog(1,1,4,1)</p>
<p>dog.head</p>
</li>
</ul>
	
	</div>
	
	<div id="current-post-cover" data-scr="https://addyzk.github.io/Random-img/28.jpg"></div>

	<!-- relate post, comment...-->
	<div class="investment-container">
		<div class="investment-header">
			<div class="investment-title-1">
				<div class="on">相关文章</div>
				<div>评论</div>
				<div>分享</div>
			</div>
			<div class="investment-title-2">	            
				
	<span>
		<a href="javascript: window.scrollTo(0, 0);">返回顶部</a>
		
			<a href="../../../05/16/hello-world/" title="Hello my friend!" rel="prev">
				&laquo;上一篇
			</a>
		
		
			<a href="../../../../2018/10/12/mysql高级/" title="mysql高级" rel="next">
				下一篇&raquo;
			</a>
			
	</span>


      		
			</div>	
		</div>
		
		<div class="investment-content">
			<div class="investment-content-list">
				

<div class="relate-post">
	
		<ul>
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../05/28/linux/" title="linux">
								linux			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								五月 28日, 2019				
							</p>
							<p class="relate-post-content">
								一、课程简介
linux服务器配置及常用命令

开发软件配置及服务环境的搭建

软件的安装和配置

mysql数据库使用、monDB使用、redius的使用

git的使用

html/css


课程学习方式
表达训练     

...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../05/28/linux/" title="linux">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/88.jpg" alt="linux">
							</a>
						</div>
					</li>											
			
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../05/16/hello-world/" title="Hello my friend!">
								Hello my friend!			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								五月 16日, 2019				
							</p>
							<p class="relate-post-content">
								Welcome to my blog ! This is your very first post. Check documentation for more info. If you get any problems when us...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../05/16/hello-world/" title="Hello my friend!">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/2.jpg" alt="Hello my friend!">
							</a>
						</div>
					</li>											
			
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../../2018/10/12/mysql高级/" title="mysql高级">
								mysql高级			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								十月 12日, 2018				
							</p>
							<p class="relate-post-content">
								#mysql数据库
一、高级1.1 子查询
子查询嵌入到其他查询语句中查询语句，子查询只能出现在from，where中
子查询不要用select *,exists除外

12345678910select title from for...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../../2018/10/12/mysql高级/" title="mysql高级">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/15.jpg" alt="mysql高级">
							</a>
						</div>
					</li>											
			
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../../2018/09/17/sql优化/" title="mysql优化">
								mysql优化			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								九月 17日, 2018				
							</p>
							<p class="relate-post-content">
								mysql优化一、数据库设计原则数据库设计的三范式学生表(学号，姓名，生日，课程名，课程成绩，等级，学院，院长)



学号
姓名
生日
课程号
课程名
成绩
等级
学院
院长




10001
张三
1998.1.1
tp3021...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../../2018/09/17/sql优化/" title="mysql优化">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/16.jpg" alt="mysql优化">
							</a>
						</div>
					</li>											
			
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../../2018/08/29/网络编程/" title="网络编程">
								网络编程			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								八月 29日, 2018				
							</p>
							<p class="relate-post-content">
								计算机之间的通信，三次握手，四次挥手！TCP/UDP协议！
17 网络编程一、网络编程1.网络编程基础
计算机网络：把分布在不同区域的计算机通过专门的设备使用通信线路连接起来，从而会形成一个庞大的网络系统，不同的计算机之间就可以进行信...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../../2018/08/29/网络编程/" title="网络编程">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/1.jpg" alt="网络编程">
							</a>
						</div>
					</li>											
			
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../../2018/05/12/redis/" title="redis">
								redis			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								五月 12日, 2018				
							</p>
							<p class="relate-post-content">
								redis教程：概述redis是一种支持分布式的nosql数据库,他的数据是保存在内存中，同时redis可以定时把内存数据同步到磁盘，即可以将数据持久化，并且他比memcached支持更多的数据结构(string,list列表[队列和...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../../2018/05/12/redis/" title="redis">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/10.jpg" alt="redis">
							</a>
						</div>
					</li>											
			
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../../2018/04/27/项目部署/" title="项目部署">
								项目部署			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								四月 27日, 2018				
							</p>
							<p class="relate-post-content">
								一、项目部署基本流程1234567891011- 虚拟环境- 数据库- 项目上传- 项目依赖- 数据迁移- Nginx- uWSGI- Nginx和uWSGI对接
二、虚拟环境12345678910111213141516171819...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../../2018/04/27/项目部署/" title="项目部署">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/99.jpg" alt="项目部署">
							</a>
						</div>
					</li>											
			
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../../2018/04/23/git/" title="Git!">
								Git!			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								四月 23日, 2018				
							</p>
							<p class="relate-post-content">
								Git 的基本认识，常用命令，以及使用流程，冲突管理分支管理等。
Git1.git简介1234- workspace 工作区- index 暂存区- repository 本地版本库- remote 远程仓库
2.常用git命令1所有...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../../2018/04/23/git/" title="Git!">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/47.jpg" alt="Git!">
							</a>
						</div>
					</li>											
			
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../../2018/04/14/mysql/" title="mysql">
								mysql			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								四月 14日, 2018				
							</p>
							<p class="relate-post-content">
								数据库一、数据库基本概念数据的仓库:  
数据库服务器–&gt;数据库—&gt;表–&gt;记录-&gt;属性
1sudo apt-get install -y mysql-server mysql-client
二、SQL基本可分为...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../../2018/04/14/mysql/" title="mysql">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/13.jpg" alt="mysql">
							</a>
						</div>
					</li>											
			
			
					<li>
						<div class="relate-post-text">
							<a class="relate-post-title" href="../../../../2018/02/18/Django-rest-framework/" title="DRF">
								DRF			
							</a>
							<p class="relate-post-date">
								<i class="fa fa-calendar"></i>
								二月 18日, 2018				
							</p>
							<p class="relate-post-content">
								一、RESTREST是”Representational State Transfer”缩写，即是”表现层状态转化”。而”表现层”其实指的是”资源(Resource)”的表现层。12表现层: 资源(例如图片、歌曲、用户....)状态转...
							</p>
						</div>

						<div class="relate-post-cover">
							<a href="../../../../2018/02/18/Django-rest-framework/" title="DRF">				
								
								<img class="lazy" src="/img/placeholder.jpg" data-src="https://addyzk.github.io/Random-img/31.jpg" alt="DRF">
							</a>
						</div>
					</li>											
			
			
		</ul>
	
</div>	
			</div>
			<div class="investment-content-list">
				<div class="layout-comment">

	

		

			<!-- gitalk comment -->
			<!-- show gitalk comment -->
<div id="gitalk-container"></div>

<!-- gitalk`s css & js -->
<link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
<link rel="stylesheet" href="/SorrisiYi/css/comment.css">
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
<script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>

<script type="text/javascript">
	//Thanks O-R
	//https://github.com/gitalk/gitalk/issues/102#issuecomment-382970552
	//去除尾部匹配正则数组的字符串  
	//Remove redundant characters
	String.prototype.trimEnd = function(regStr) {
		var result = this;
		if(regStr == undefined || regStr == null || regStr == "") {
			return result;
		}
		var array = regStr.split(',');

		if(array.length > 0) {

			var c = array.shift();
			var str = this;
			var i = str.length;
			var rg = new RegExp(c);
			var matchArr = str.match(rg);

			if(matchArr != undefined && matchArr != null && matchArr.length > 0) {
				var matchStr = matchArr[0].replace(/\\/g, "\\\\").replace(/\*/g, "\\*")
					.replace(/\+/g, "\\+").replace(/\|/g, "\\|")
					.replace(/\{/g, "\\{").replace(/\}/g, "\\}")
					.replace(/\(/g, "\\(").replace(/\)/g, "\\)")
					.replace(/\^/g, "\\^").replace(/\$/g, "\\$")
					.replace(/\[/g, "\\[").replace(/\]/g, "\\]")
					.replace(/\?/g, "\\?").replace(/\,/g, "\\,")
					.replace(/\./g, "\\.").replace(/\&/g, "\\&");
				matchStr = matchStr + '$';
				result = str.replace(new RegExp(matchStr), "");
			}

			if(array.length > 0) {
				return result.trimEnd(array.join())
			} else {
				return result;
			}
		}
	};

	//Create gitalk
	var gitalk = new Gitalk({
		clientID: 'fa840d66074e8a6722c9',
		clientSecret: '039c6b559c7710f00e235c26795a2e2ecb613161',
		//id: window.location.pathname,
		//id: decodeURI(window.location.pathname),
		//id: (window.location.pathname).split("/").pop().substring(0, 49),
		id: decodeURI( md5( location.href.trimEnd('#.*$,\\?.*$,index.html$') ) ),
		repo: 'annie-gitalk',
		owner: 'SorrisoYi',
		admin: 'SorrisoYi',
		distractionFreeMode: 'true',
	})
	gitalk.render('gitalk-container');
</script>

		
		
	

</div>
			</div>
			<div class="investment-content-list">
				<div class="layout-share">
	
	

		

			<!-- addThis share -->
			<!-- www.addthis.com/dashboard -->

	<div class="addthis_inline_share_toolbox">
	</div>

	<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-xxx" async="async"></script>


		
		
	
</div>


			</div>
		</div>	
	</div>
	</div>
</div>



	<!-- leancloud -->
	<!--
	时间：2018-11-27
	描述：
		文章访问量：visitors
		文章喜欢量：likes	
		文章排行榜：topNPost
		其他得说明：
			01-Cookie相关的函数 
				https://blog.csdn.net/somehow1002/article/details/78511541（Author：somehow1002）
			02-visitors相关的函数 
				https://blog.csdn.net/u013553529/article/details/63357382（Author：爱博客大伯）
				https://notes.doublemine.me/2015-10-21-为NexT主题添加文章阅读量统计功能.html（Author：夏末）
			03-topNPost相关的函数
				https://hoxis.github.io/hexo-next-read-rank.html（Author：hoxis）
			04-likes相关的函数，
				参考了01 & 02进行简单的设计与实现
-->



	<script>
		var appid = 'bdanoXQN5zgeVyspG5e9RF7o-gzGzoHsz',
            appkey = 'RVVmwDan5FhjuwkKxenjOGSE';	  
        AnnieLeancloud(appid, appkey);         
	</script>
    

	


<!-- show math formula -->



	 
	<script src="../../../../plugin/clipboard/clipboard.js"></script>
	<script>
		// Copy code !
	    function codePreprocessing() {
	        $("#article-content .highlight").each(function() {

	            $(this).wrap('<div id="post-code"></div>');

	        })

	        $("#article-content #post-code").each(function() {

	            $(this).prepend('<nav class="copy-nav"><span><i class="code-language"></i></span></nav>');

	        })

	        $("#article-content .copy-nav").each(function() {
	            var temp = $(this).next().attr('class'),
	                language = ((temp.length > 9) && (temp != null)) ? temp.substr(10) : "none"; //why 9? Need to check language?

	            $(this).find('.code-language').text(language);

	            $(this).append('<span class="copy-btn"><i class="fa fa-copy" aria-hidden="true"></i></span>');

	        });
	    }

		function codeCopy() {
		    $('#article-content #post-code').each(function(i) {
		        var codeCopyId = 'codeCopy-' + i;

		        var codeNode = $(this).find('.code'),
		            copyButton = $(this).find('.copy-btn');

		        codeNode.attr('id', codeCopyId);
		        copyButton.attr('data-clipboard-target-id', codeCopyId);
		    })

		    
			var clipboard = new ClipboardJS('.copy-btn', {
					target: function(trigger) {
						return document.getElementById(trigger.getAttribute('data-clipboard-target-id'));
					}
		      	});

			//pure js
			function showTooltip(elem, msg) {		   
				elem.setAttribute('aria-label', msg);
				elem.setAttribute('class', 'copy-btn copy-status');
				setTimeout(function() {
					elem.setAttribute('class', 'copy-btn');
				}, 2000);
			}

			clipboard.on('success', function(e) {
			    e.clearSelection();
			    console.info('Action:', e.action);		   
			    console.info('Trigger:', e.trigger);
			    showTooltip(e.trigger, 'Copied!');
			    
			});
			clipboard.on('error', function(e) {
			    console.error('Action:', e.action);
			    console.error('Trigger:', e.trigger);
			});
		

		}

		if ($('.layout-post').length) {
		    codePreprocessing();
		    codeCopy();
		} 
	</script>





<link rel="stylesheet" href="../../../../plugin/fancybox/jquery.fancybox.css">
<script src="../../../../plugin/fancybox/jquery.fancybox.js"></script>

<script type="text/javascript">
	var titleID = $('.article-title a'),
		imageID = $('.article-content img'),
		videoID = $('.article-content video');

	var postTitle = titleID.text() ? titleID.text() : "No post title!";

	imageID.each(function() {
		var imgPath = $(this).attr('src'),
			imgTitle = $(this).attr('alt') ? $(this).attr('alt') : "No image description!";

		//给每个匹配的<img>元素打包, 即添加父元素<a>
		$(this).wrap('<a data-fancybox="gallery" data-caption=" 《 ' + postTitle + ' 》 ' + imgTitle + ' "  href=" ' + imgPath + ' "> </a>');
	});

	videoID.each(function() {
		var videoPath = $(this).attr('src');

		//给每个匹配的<img>元素打包, 即添加父元素<a>
		$(this).wrap('<a data-fancybox href=" ' + videoPath + ' "> </a>');
	});
	//TODO：支持html5 video

	if($('#layout-post').length) {
		$('[data-fancybox="gallery"]').fancybox({
			loop: true,
			buttons: [
				"zoom",
				"share",
				"slideShow",
				"fullScreen",
				//"download",
				"thumbs",
				"close"
			],
			protect: false
		});
	}
</script>
		</main>

		<!--footer-->
		<footer>
	<div class="social">
		<ul>
	
		<li>
			<a href="http://github.com/addyzk" target="_blank">
				<i class="fa fa-github"></i>
			</a>
		</li>
	
		<li>
			<a href="https://weibo.com/u/2943549915" target="_blank">
				<i class="fa fa-weibo"></i>
			</a>
		</li>
	
		<li>
			<a href="http://github.com/" target="_blank">
				<i class="fa fa-pinterest"></i>
			</a>
		</li>
	
		<li>
			<a href="http://github.com/" target="_blank">
				<i class="fa fa-instagram"></i>
			</a>
		</li>
	
		<li>
			<a href="http://github.com/" target="_blank">
				<i class="fa fa-twitter"></i>
			</a>
		</li>
	
		<li>
			<a href="../../../../atom.xml" target="_blank">
				<i class="fa fa-rss"></i>
			</a>
		</li>
			
</ul>

	</div>
		
	<div class="copyright">
		<p>
			 
				&copy;2016 - 2019, content by SorrisoYi. All Rights Reserved.
			
			
			

	<!-- busuanzi -->
	<!-- busuanzi -->

		
	<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
	

		<span id="busuanzi_container_page_pv">
	  		本文总阅读量<span id="busuanzi_value_page_pv"></span>次
		</span>

	




		</p>
		<p>
			<a href="http://hexo.io/" title="Hexo" target="_blank" rel="noopener">Hexo</a> Theme <a href="https://github.com/Sariay/hexo-theme-Annie" title="Annie" target="_blank" rel="noopener">Annie</a> by Sariay.
			<a href="javascript:zh_tran('s');" class="zh_click" id="zh_click_s">简体</a> 
			<a href="javascript:zh_tran('t');" class="zh_click" id="zh_click_t">繁體</a>				
		</p>
	</div>		
</footer>
		
	<!-- set '1' to show motto in all pages! -->

	<script src="../../../../plugin/motto/motto.js"></script>
	
	<script type="text/javascript">
		$(".motto").html( getMingYanContent() );
	</script>	




	<!--
	时间：2018-10-3
	描述：
		插件名称：hexo-generator-search-zip
		插件来源: https://github.com/SuperKieran/hexo-generator-search-zip
		代码参考：https://github.com/SuperKieran/TKL/blob/master/layout/_partial/search.ejs(Include: js & css)	
-->
<div class="popup search-popup local-search-popup">
	<div class="local-search-container">
		<span class="popup-btn-close">
      		ESC
   		</span>
		<div class="local-search-header">
			<div class="input-prompt">				
			</div>
			<input autocomplete="off" placeholder="Search..." type="text" id="local-search-input">
		</div>
		<div class="local-search-body">
			<div id="local-search-output"></div>
		</div>
		<div class="local-search-footer">
			<div class="topN-post">				
				

   
	<div id="topN">
		<div class="topN-title" data-title="热门文章"></div> 
	</div>
	
    <script>
        var appid = 'bdanoXQN5zgeVyspG5e9RF7o-gzGzoHsz',
            appkey = 'RVVmwDan5FhjuwkKxenjOGSE',
            limitCount = 10;
        if( $('#topN').length ){
            AV.initialize(appid, appkey);
            var Counter = AV.Object.extend("Counter");  
            topNPost(Counter, limitCount);
        }
    </script>
   
								
			</div>
		</div>
	</div>
</div>

<script src="../../../../plugin/search/ziploader.js"></script>
<script src="../../../../plugin/search/search.js"></script>

<script type="text/javascript">
	var search_path = 'search.json',
		zip_Path = '/SorrisiYi/search.zip',
		version_Path = '/SorrisiYi/searchVersion.txt',
		input_Trigger = 'auto',
		top_N = '2';

	themeLocalSearch({
		search_path, 
		zip_Path, 
		version_Path, 
		input_Trigger, 
		top_N
	});
</script>


<!-- love effect -->

	<script src="../../../../plugin/love/love.js"></script>


<!-- back to top -->

	
	<div id="totop">
  		<a href="javascript:;" name="TOTOP" class="fa fa-arrow-up"></a>
	</div>




<!-- site analysis -->


	<!-- site-analysis -->
	
	
	
	
	
 

<script src="../../../../plugin/vibrant/vibrant.js"></script>
<script src="../../../../plugin/chinese/chinese.js"></script>
<script src="../../../../plugin/imgLazyLoader/yall.min.js"></script>
<script src="../../../../plugin/imgResize/jquery.resizeimagetoparent.min.js"></script>
<script src="../../../../plugin/nicescroll/jquery.nicescroll.js"></script>
<script src="../../../../js/resizediv.js"></script>
<script src="../../../../js/main.js"></script>
	</body>	
</html>